home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / IMAGE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-19  |  26.6 KB  |  1,415 lines  |  [TEXT/CWIE]

  1. /****************************************************************************
  2. *                image.c
  3. *
  4. *  This module implements the mapped textures including image map, bump map
  5. *  and material map.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include "frame.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28. #include "texture.h"
  29. #include "image.h"
  30. #include "matrices.h"
  31. #include "povray.h"
  32.  
  33.  
  34.  
  35. /*****************************************************************************
  36. * Local preprocessor defines
  37. ******************************************************************************/
  38.  
  39.  
  40.  
  41. /*****************************************************************************
  42. * Local typedefs
  43. ******************************************************************************/
  44.  
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local variables
  49. ******************************************************************************/
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Static functions
  55. ******************************************************************************/
  56.  
  57. static int cylindrical_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  58. static int torus_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  59. static int spherical_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  60. static int planar_image_map PARAMS((VECTOR EPoint, IMAGE * Image, DBL *u, DBL *v));
  61. static void no_interpolation PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  62. static DBL bilinear PARAMS((DBL *corners, DBL x, DBL y));
  63. static DBL norm_dist PARAMS((DBL *corners, DBL x, DBL y));
  64. static void Interp PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  65. static void image_colour_at PARAMS((IMAGE * Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index));
  66. static int map PARAMS((VECTOR EPoint, TPATTERN * Turb, DBL *xcoor, DBL *ycoor));
  67.  
  68. /*
  69.  * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  70.  * 
  71.  * A. Simplistic (planar) method of image projection devised by DKB and AAC:
  72.  * 
  73.  * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  74.  * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  75.  * that position on the 2-d plane of "Image". 3. Map colour value in Image
  76.  * [0..255] to a more normal colour range [0..1].
  77.  * 
  78.  * B. Specialized shape projection variations by Alexander Enzmann:
  79.  * 
  80.  * 1. Cylindrical mapping 2. Spherical mapping 3. Torus mapping
  81.  */
  82.  
  83. /*****************************************************************************
  84. *
  85. * FUNCTION
  86. *
  87. *   image_map
  88. *
  89. * INPUT
  90. *
  91. *   EPoint   -- 3-D point at which function is evaluated
  92. *   Pigment  -- Pattern containing various parameters
  93. *
  94. * OUTPUT
  95. *
  96. *   Colour   -- color at EPoint
  97. *
  98. * RETURNS
  99. *
  100. *   int - TRUE,  if current point on the image map
  101. *         FALSE, if current point is not on the image map
  102. *
  103. * AUTHOR
  104. *
  105. *   POV-Ray Team
  106. *
  107. * DESCRIPTION   : Determines color of a 3-D point from a 2-D bitmap
  108. *
  109. * CHANGES
  110. *
  111. ******************************************************************************/
  112.  
  113. int image_map(EPoint, Pigment, colour)
  114. VECTOR EPoint;
  115. PIGMENT *Pigment;
  116. COLOUR colour;
  117. {
  118.   int reg_number;
  119.   DBL xcoor = 0.0, ycoor = 0.0;
  120.  
  121.   /* If outside map coverage area, return clear */
  122.  
  123.   if (map(EPoint, ((TPATTERN *) Pigment), &xcoor, &ycoor))
  124.   {
  125.     Make_ColourA(colour, 1.0, 1.0, 1.0, 0.0, 1.0);
  126.  
  127.     return(FALSE);
  128.   }
  129.   else
  130.   {
  131.     image_colour_at(Pigment->Vals.Image, xcoor, ycoor, colour, ®_number);
  132.   }
  133.  
  134.   return(TRUE);
  135. }
  136.  
  137.  
  138.  
  139. /*****************************************************************************
  140. *
  141. * FUNCTION
  142. *
  143. * INPUT
  144. *
  145. * OUTPUT
  146. *
  147. * RETURNS
  148. *
  149. * AUTHOR
  150. *
  151. * DESCRIPTION
  152. *
  153. *   Very different stuff than the other routines here. This routine takes an
  154. *   intersection point and a texture and returns a new texture based on the
  155. *   index/color of that point in an image/materials map. CdW 7/91
  156. *
  157. * CHANGES
  158. *
  159. ******************************************************************************/
  160.  
  161. TEXTURE *material_map(EPoint, Texture)
  162. VECTOR EPoint;
  163. TEXTURE *Texture;
  164. {
  165.   int reg_number = 0;
  166.   int Material_Number;
  167.   int numtex;
  168.   DBL xcoor = 0.0, ycoor = 0.0;
  169.   COLOUR colour;
  170.   TEXTURE *Temp_Tex;
  171.  
  172.   /*
  173.    * Now we have transformed x, y, z we use image mapping routine to determine
  174.    * texture index.
  175.    */
  176.  
  177.   if (map(EPoint, ((TPATTERN *) Texture), &xcoor, &ycoor))
  178.   {
  179.     Material_Number = 0;
  180.   }
  181.   else
  182.   {
  183.     Make_ColourA(colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  184.  
  185.     image_colour_at(Texture->Vals.Image, xcoor, ycoor, colour, ®_number);
  186.  
  187.     if (Texture->Vals.Image->Colour_Map == NULL)
  188.     {
  189.       Material_Number = (int)(colour[RED] * 255.0);
  190.     }
  191.     else
  192.     {
  193.       Material_Number = reg_number;
  194.     }
  195.   }
  196.  
  197.   if (Material_Number > Texture->Num_Of_Mats)
  198.   {
  199.     Material_Number %= Texture->Num_Of_Mats;
  200.   }
  201.  
  202.   for (numtex = 0, Temp_Tex = Texture->Materials;
  203.        (Temp_Tex->Next_Material != NULL) && (numtex < Material_Number);
  204.        Temp_Tex = Temp_Tex->Next_Material, numtex++)
  205.   {
  206.     /* do nothing */
  207.   }
  208.  
  209.   return (Temp_Tex);
  210. }
  211.  
  212.  
  213.  
  214. /*****************************************************************************
  215. *
  216. * FUNCTION
  217. *
  218. * INPUT
  219. *
  220. * OUTPUT
  221. *
  222. * RETURNS
  223. *
  224. * AUTHOR
  225. *
  226. * DESCRIPTION
  227. *
  228. * CHANGES
  229. *
  230. ******************************************************************************/
  231.  
  232. void bump_map(EPoint, Tnormal, normal)
  233. VECTOR EPoint;
  234. TNORMAL *Tnormal;
  235. VECTOR normal;
  236. {
  237.   DBL xcoor = 0.0, ycoor = 0.0;
  238.   int index, index2, index3;
  239.   COLOUR colour1, colour2, colour3;
  240.   VECTOR p1, p2, p3;
  241.   VECTOR bump_normal;
  242.   VECTOR xprime, yprime, zprime, Temp;
  243.   DBL Length;
  244.   DBL Amount = Tnormal->Amount;
  245.   IMAGE *Image = Tnormal->Vals.Image;
  246.  
  247.   Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0);
  248.   Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0);
  249.   Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0);
  250.  
  251.   /* going to have to change this */
  252.   /* need to know if bump point is off of image for all 3 points */
  253.  
  254.   if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor))
  255.   {
  256.     return;
  257.   }
  258.   else
  259.   {
  260.     image_colour_at(Image, xcoor, ycoor, colour1, &index);
  261.   }
  262.  
  263.   xcoor--;
  264.   ycoor++;
  265.  
  266.   if (xcoor < 0.0)
  267.   {
  268.     xcoor += (DBL)Image->iwidth;
  269.   }
  270.   else
  271.   {
  272.     if (xcoor >= Image->iwidth)
  273.     {
  274.       xcoor -= (DBL)Image->iwidth;
  275.     }
  276.   }
  277.  
  278.   if (ycoor < 0.0)
  279.   {
  280.     ycoor += (DBL)Image->iheight;
  281.   }
  282.   else
  283.   {
  284.     if (ycoor >= (DBL)Image->iheight)
  285.     {
  286.       ycoor -= (DBL)Image->iheight;
  287.     }
  288.   }
  289.  
  290.   image_colour_at(Image, xcoor, ycoor, colour2, &index2);
  291.  
  292.   xcoor += 2.0;
  293.  
  294.   if (xcoor < 0.0)
  295.   {
  296.     xcoor += (DBL)Image->iwidth;
  297.   }
  298.   else
  299.   {
  300.     if (xcoor >= Image->iwidth)
  301.     {
  302.       xcoor -= (DBL)Image->iwidth;
  303.     }
  304.   }
  305.  
  306.   image_colour_at(Image, xcoor, ycoor, colour3, &index3);
  307.  
  308.   if (Image->Colour_Map == NULL || Image->Use_Colour_Flag)
  309.   {
  310.     p1[X] = 0;
  311.     p1[Y] = Amount * (0.229 * colour1[RED] + 0.587 * colour1[GREEN] + 0.114 * colour1[BLUE]);
  312.     p1[Z] = 0;
  313.  
  314.     p2[X] = 0;
  315.     p2[Y] = Amount * (0.229 * colour2[RED] + 0.587 * colour2[GREEN] + 0.114 * colour2[BLUE]);
  316.     p2[Z] = 1;
  317.  
  318.     p3[X] = 1;
  319.     p3[Y] = Amount * (0.229 * colour3[RED] + 0.587 * colour3[GREEN] + 0.114 * colour3[BLUE]);
  320.     p3[Z] = 1;
  321.   }
  322.   else
  323.   {
  324.     p1[X] = 0;
  325.     p1[Y] = Amount * index;
  326.     p1[Z] = 0;
  327.  
  328.     p2[X] = 0;
  329.     p2[Y] = Amount * index2;
  330.     p2[Z] = 1;
  331.  
  332.     p3[X] = 1;
  333.     p3[Y] = Amount * index3;
  334.     p3[Z] = 1;
  335.   }
  336.  
  337.   /* we have points 1,2,3 for a triangle now we need the surface normal for it */
  338.  
  339.   VSub(xprime, p1, p2);
  340.   VSub(yprime, p3, p2);
  341.   VCross(bump_normal, yprime, xprime);
  342.   VNormalize(bump_normal, bump_normal);
  343.  
  344.   Assign_Vector(yprime, normal);
  345.   Make_Vector(Temp, 0.0, 1.0, 0.0);
  346.   VCross(xprime, yprime, Temp);
  347.   VLength(Length, xprime);
  348.  
  349.   if (Length < EPSILON)
  350.   {
  351.     if (fabs(normal[Y] - 1.0) < Small_Tolerance)
  352.     {
  353.       Make_Vector(yprime, 0.0, 1.0, 0.0);
  354.       Make_Vector(xprime, 1.0, 0.0, 0.0);
  355.       Length = 1.0;
  356.     }
  357.     else
  358.     {
  359.       Make_Vector(yprime, 0.0, -1.0, 0.0);
  360.       Make_Vector(xprime, 1.0, 0.0, 0.0);
  361.       Length = 1.0;
  362.     }
  363.   }
  364.  
  365.   VScaleEq(xprime, 1.0 / Length);
  366.   VCross(zprime, xprime, yprime);
  367.   VNormalizeEq(zprime);
  368.   VScaleEq(xprime, bump_normal[X]);
  369.   VScaleEq(yprime, bump_normal[Y]);
  370.   VScaleEq(zprime, bump_normal[Z]);
  371.   VAdd(Temp, xprime, yprime);
  372.   VAdd(normal, Temp, zprime);
  373. }
  374.  
  375.  
  376.  
  377. /*****************************************************************************
  378. *
  379. * FUNCTION
  380. *
  381. * INPUT
  382. *
  383. * OUTPUT
  384. *
  385. * RETURNS
  386. *
  387. * AUTHOR
  388. *
  389. * DESCRIPTION
  390. *
  391. * CHANGES
  392. *
  393. ******************************************************************************/
  394.  
  395. static void image_colour_at(Image, xcoor, ycoor, colour, index)
  396. IMAGE *Image;
  397. DBL xcoor, ycoor;
  398. COLOUR colour;
  399. int *index;
  400. {
  401.   switch (Image->Interpolation_Type)
  402.   {
  403.     case NO_INTERPOLATION:
  404.  
  405.       no_interpolation(Image, xcoor, ycoor, colour, index);
  406.  
  407.       break;
  408.  
  409.     default:
  410.  
  411.       Interp(Image, xcoor, ycoor, colour, index);
  412.  
  413.       break;
  414.   }
  415. }
  416.  
  417.  
  418.  
  419. /*****************************************************************************
  420. *
  421. * FUNCTION
  422. *
  423. * INPUT
  424. *
  425. * OUTPUT
  426. *
  427. * RETURNS
  428. *
  429. * AUTHOR
  430. *
  431. * DESCRIPTION
  432. *
  433. *   Map a point (x, y, z) on a cylinder of radius 1, height 1, that has its axis
  434. *   of symmetry along the y-axis to the square [0,1]x[0,1].
  435. *
  436. * CHANGES
  437. *
  438. ******************************************************************************/
  439.  
  440. static int cylindrical_image_map(EPoint, Image, u, v)
  441. VECTOR EPoint;
  442. IMAGE *Image;
  443. DBL *u, *v;
  444. {
  445.   DBL len, theta;
  446.   DBL x = EPoint[X];
  447.   DBL y = EPoint[Y];
  448.   DBL z = EPoint[Z];
  449.  
  450.   if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  451.   {
  452.     return 0;
  453.   }
  454.  
  455.   *v = fmod(y * Image->height, Image->height);
  456.  
  457.   /* Make sure this vector is on the unit sphere. */
  458.  
  459.   len = sqrt(x * x + y * y + z * z);
  460.  
  461.   if (len == 0.0)
  462.   {
  463.     return 0;
  464.   }
  465.   else
  466.   {
  467.     x /= len;
  468.     z /= len;
  469.   }
  470.  
  471.   /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  472.  
  473.   len = sqrt(x * x + z * z);
  474.  
  475.   if (len == 0.0)
  476.   {
  477.     return 0;
  478.   }
  479.   else
  480.   {
  481.     if (z == 0.0)
  482.     {
  483.       if (x > 0)
  484.       {
  485.         theta = 0.0;
  486.       }
  487.       else
  488.       {
  489.         theta = M_PI;
  490.       }
  491.     }
  492.     else
  493.     {
  494.       theta = acos(x / len);
  495.  
  496.       if (z < 0.0)
  497.       {
  498.         theta = TWO_M_PI - theta;
  499.       }
  500.     }
  501.  
  502.     theta /= TWO_M_PI;  /* This will be from 0 to 1 */
  503.   }
  504.  
  505.   *u = (theta * Image->width);
  506.  
  507.   return 1;
  508. }
  509.  
  510.  
  511.  
  512. /*****************************************************************************
  513. *
  514. * FUNCTION
  515. *
  516. * INPUT
  517. *
  518. * OUTPUT
  519. *
  520. * RETURNS
  521. *
  522. * AUTHOR
  523. *
  524. * DESCRIPTION
  525. *
  526. *   Map a point (x, y, z) on a torus  to a 2-d image.
  527. *
  528. * CHANGES
  529. *
  530. ******************************************************************************/
  531.  
  532. static int torus_image_map(EPoint, Image, u, v)
  533. VECTOR EPoint;
  534. IMAGE *Image;
  535. DBL *u, *v;
  536. {
  537.   DBL len, phi, theta;
  538.   DBL r0;
  539.   DBL x = EPoint[X];
  540.   DBL y = EPoint[Y];
  541.   DBL z = EPoint[Z];
  542.  
  543.   r0 = Image->Gradient[X];
  544.  
  545.   /* Determine its angle from the x-axis. */
  546.  
  547.   len = sqrt(x * x + z * z);
  548.  
  549.   if (len == 0.0)
  550.   {
  551.     return 0;
  552.   }
  553.   else
  554.   {
  555.     if (z == 0.0)
  556.     {
  557.       if (x > 0)
  558.       {
  559.         theta = 0.0;
  560.       }
  561.       else
  562.       {
  563.         theta = M_PI;
  564.       }
  565.     }
  566.     else
  567.     {
  568.       theta = acos(x / len);
  569.  
  570.       if (z < 0.0)
  571.       {
  572.         theta = TWO_M_PI - theta;
  573.       }
  574.     }
  575.   }
  576.  
  577.   theta = 0.0 - theta;
  578.  
  579.   /* Now rotate about the y-axis to get the point (x, y, z) into the x-y plane. */
  580.  
  581.   x = len - r0;
  582.  
  583.   len = sqrt(x * x + y * y);
  584.  
  585.   phi = acos(-x / len);
  586.  
  587.   if (y > 0.0)
  588.   {
  589.     phi = TWO_M_PI - phi;
  590.   }
  591.  
  592.   /* Determine the parametric coordinates. */
  593.  
  594.   theta /= TWO_M_PI;
  595.  
  596.   phi /= TWO_M_PI;
  597.  
  598.   *u = (-theta * Image->width);
  599.  
  600.   *v = (phi * Image->height);
  601.  
  602.   return 1;
  603. }
  604.  
  605.  
  606.  
  607. /*****************************************************************************
  608. *
  609. * FUNCTION
  610. *
  611. * INPUT
  612. *
  613. * OUTPUT
  614. *
  615. * RETURNS
  616. *
  617. * AUTHOR
  618. *
  619. * DESCRIPTION
  620. *
  621. *   Map a point (x, y, z) on a sphere of radius 1 to a 2-d image. (Or is it the
  622. *   other way around?)
  623. *
  624. * CHANGES
  625. *
  626. ******************************************************************************/
  627.  
  628. static int spherical_image_map(EPoint, Image, u, v)
  629. VECTOR EPoint;
  630. IMAGE *Image;
  631. DBL *u, *v;
  632. {
  633.   DBL len, phi, theta;
  634.   DBL x = EPoint[X];
  635.   DBL y = EPoint[Y];
  636.   DBL z = EPoint[Z];
  637.  
  638.   /* Make sure this vector is on the unit sphere. */
  639.  
  640.   len = sqrt(x * x + y * y + z * z);
  641.  
  642.   if (len == 0.0)
  643.   {
  644.     return 0;
  645.   }
  646.   else
  647.   {
  648.     x /= len;
  649.     y /= len;
  650.     z /= len;
  651.   }
  652.  
  653.   /* Determine its angle from the x-z plane. */
  654.  
  655.   phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */
  656.  
  657.  
  658.   /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  659.  
  660.   len = sqrt(x * x + z * z);
  661.  
  662.   if (len == 0.0)
  663.   {
  664.     /* This point is at one of the poles. Any value of xcoord will be ok... */
  665.  
  666.     theta = 0;
  667.   }
  668.   else
  669.   {
  670.     if (z == 0.0)
  671.     {
  672.       if (x > 0)
  673.       {
  674.         theta = 0.0;
  675.       }
  676.       else
  677.       {
  678.         theta = M_PI;
  679.       }
  680.     }
  681.     else
  682.     {
  683.       theta = acos(x / len);
  684.  
  685.       if (z < 0.0)
  686.       {
  687.         theta = TWO_M_PI - theta;
  688.       }
  689.     }
  690.  
  691.     theta /= TWO_M_PI;  /* This will be from 0 to 1 */
  692.   }
  693.  
  694.   *u = (theta * Image->width);
  695.   *v = (phi * Image->height);
  696.  
  697.   return 1;
  698. }
  699.  
  700. /*
  701.  * 2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  702.  * 
  703.  * Simplistic planar method of object image projection devised by DKB and AAC.
  704.  * 
  705.  * 1. Transform texture in 3-D space if requested. 2. Determine local object 2-d
  706.  * coords from 3-d coords by <X Y Z> triple. 3. Return pixel color value at
  707.  * that position on the 2-d plane of "Image". 3. Map colour value in Image
  708.  * [0..255] to a more normal colour range [0..1].
  709.  */
  710.  
  711.  
  712.  
  713. /*****************************************************************************
  714. *
  715. * FUNCTION
  716. *
  717. * INPUT
  718. *
  719. * OUTPUT
  720. *
  721. * RETURNS
  722. *
  723. * AUTHOR
  724. *
  725. * DESCRIPTION
  726. *
  727. *   Return 0 if there is no color at this point (i.e. invisible), return 1 if a
  728. *   good mapping is found.
  729. *
  730. * CHANGES
  731. *
  732. ******************************************************************************/
  733.  
  734. static int planar_image_map(EPoint, Image, u, v)
  735. VECTOR EPoint;
  736. IMAGE *Image;
  737. DBL *u, *v;
  738. {
  739.   DBL x = EPoint[X];
  740.   DBL y = EPoint[Y];
  741.   DBL z = EPoint[Z];
  742.  
  743.   if (Image->Gradient[X] != 0.0)
  744.   {
  745.     if ((Image->Once_Flag) && ((x < 0.0) || (x > 1.0)))
  746.     {
  747.       return 0;
  748.     }
  749.  
  750.     if (Image->Gradient[X] > 0)
  751.     {
  752.       *u = fmod(x * Image->width, Image->width);
  753.     }
  754.     else
  755.     {
  756.       *v = fmod(x * Image->height, Image->height);
  757.     }
  758.   }
  759.  
  760.   if (Image->Gradient[Y] != 0.0)
  761.   {
  762.     if ((Image->Once_Flag) && ((y < 0.0) || (y > 1.0)))
  763.     {
  764.       return 0;
  765.     }
  766.  
  767.     if (Image->Gradient[Y] > 0)
  768.     {
  769.       *u = fmod(y * Image->width, Image->width);
  770.     }
  771.     else
  772.     {
  773.       *v = fmod(y * Image->height, Image->height);
  774.     }
  775.   }
  776.  
  777.   if (Image->Gradient[Z] != 0.0)
  778.   {
  779.     if ((Image->Once_Flag) && ((z < 0.0) || (z > 1.0)))
  780.     {
  781.       return 0;
  782.     }
  783.  
  784.     if (Image->Gradient[Z] > 0)
  785.     {
  786.       *u = fmod(z * Image->width, Image->width);
  787.     }
  788.     else
  789.     {
  790.       *v = fmod(z * Image->height, Image->height);
  791.     }
  792.   }
  793.  
  794.   return 1;
  795. }
  796.  
  797.  
  798. /*****************************************************************************
  799. *
  800. * FUNCTION
  801. *
  802. *   map
  803. *
  804. * INPUT
  805. *
  806. *   EPoint   -- 3-D point at which function is evaluated
  807. *   TPattern -- Pattern containing various parameters
  808. *
  809. * OUTPUT
  810. *
  811. *   xcoor, ycoor -- 2-D result
  812. *
  813. * RETURNS
  814. *
  815. *   Map returns 1 if point off of map 0 if on map
  816. *
  817. * AUTHOR
  818. *
  819. *   POV-Ray Team
  820. *
  821. * DESCRIPTION   : Maps a 3-D point to a 2-D point depending upon map type
  822. *
  823. * CHANGES
  824. *
  825. ******************************************************************************/
  826.  
  827. static int map(EPoint, TPattern, xcoor, ycoor)
  828. VECTOR EPoint;
  829. TPATTERN *TPattern;
  830. DBL *xcoor, *ycoor;
  831. {
  832.   IMAGE *Image = TPattern->Vals.Image;
  833.  
  834.   /* Now determine which mapper to use. */
  835.  
  836.   switch (Image->Map_Type)
  837.   {
  838.     case PLANAR_MAP:
  839.  
  840.       if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  841.       {
  842.         return (1);
  843.       }
  844.  
  845.       break;
  846.  
  847.     case SPHERICAL_MAP:
  848.  
  849.       if (!spherical_image_map(EPoint, Image, xcoor, ycoor))
  850.       {
  851.         return (1);
  852.       }
  853.  
  854.       break;
  855.  
  856.     case CYLINDRICAL_MAP:
  857.  
  858.       if (!cylindrical_image_map(EPoint, Image, xcoor, ycoor))
  859.       {
  860.         return (1);
  861.       }
  862.  
  863.       break;
  864.  
  865.     case TORUS_MAP:
  866.  
  867.       if (!torus_image_map(EPoint, Image, xcoor, ycoor))
  868.       {
  869.         return (1);
  870.       }
  871.  
  872.       break;
  873.  
  874.     default:
  875.  
  876.       if (!planar_image_map(EPoint, Image, xcoor, ycoor))
  877.       {
  878.         return (1);
  879.       }
  880.  
  881.       break;
  882.   }
  883.  
  884.   /* Now make sure the point is on the image */
  885.  
  886.   *ycoor += Small_Tolerance;
  887.   *xcoor += Small_Tolerance;
  888.  
  889.   /* Compensate for y coordinates on the images being upsidedown */
  890.  
  891.   *ycoor = (DBL)Image->iheight - *ycoor;
  892.  
  893.   if (*xcoor < 0.0)
  894.   {
  895.     *xcoor += (DBL)Image->iwidth;
  896.   }
  897.   else
  898.   {
  899.     if (*xcoor >= (DBL)Image->iwidth)
  900.     {
  901.       *xcoor -= (DBL)Image->iwidth;
  902.     }
  903.   }
  904.  
  905.   if (*ycoor < 0.0)
  906.   {
  907.     *ycoor += (DBL)Image->iheight;
  908.   }
  909.   else
  910.   {
  911.     if (*ycoor >= (DBL)Image->iheight)
  912.     {
  913.       *ycoor -= (DBL)Image->iheight;
  914.     }
  915.   }
  916.  
  917.   if ((*xcoor >= (DBL)Image->iwidth) ||
  918.       (*ycoor >= (DBL)Image->iheight) ||
  919.       (*xcoor < 0.0) || (*ycoor < 0.0))
  920.   {
  921.     Error("Picture index out of range.");
  922.   }
  923.  
  924.   return (0);
  925. }
  926.  
  927.  
  928.  
  929. /*****************************************************************************
  930. *
  931. * FUNCTION
  932. *
  933. * INPUT
  934. *
  935. * OUTPUT
  936. *
  937. * RETURNS
  938. *
  939. * AUTHOR
  940. *
  941. * DESCRIPTION
  942. *
  943. * CHANGES
  944. *
  945. ******************************************************************************/
  946.  
  947. static void no_interpolation(Image, xcoor, ycoor, colour, index)
  948. IMAGE *Image;
  949. DBL xcoor, ycoor;
  950. COLOUR colour;
  951. int *index;
  952. {
  953.   IMAGE_LINE *line;
  954.   int iycoor, ixcoor;
  955.   IMAGE_COLOUR *map_colour;
  956.  
  957.   if (xcoor < 0.0)
  958.   {
  959.     xcoor += (DBL)Image->iwidth;
  960.   }
  961.   else
  962.   {
  963.     if (xcoor >= (DBL)Image->iwidth)
  964.     {
  965.       xcoor -= (DBL)Image->iwidth;
  966.     }
  967.   }
  968.  
  969.   if (ycoor < 0.0)
  970.   {
  971.     ycoor += (DBL)Image->iheight;
  972.   }
  973.   else
  974.   {
  975.     if (ycoor >= (DBL)Image->iheight)
  976.     {
  977.       ycoor -= (DBL)Image->iheight;
  978.     }
  979.   }
  980.  
  981.   iycoor = (int)ycoor;
  982.   ixcoor = (int)xcoor;
  983.  
  984.   if (Image->Colour_Map == NULL)
  985.   {
  986.     line = &Image->data.rgb_lines[iycoor];
  987.  
  988.     colour[RED] += (DBL)line->red[ixcoor] / 255.0;
  989.     colour[GREEN] += (DBL)line->green[ixcoor] / 255.0;
  990.     colour[BLUE] += (DBL)line->blue[ixcoor] / 255.0;
  991.     if (line->transm != NULL)
  992.     {
  993.       colour[TRANSM] += (DBL)line->transm[ixcoor] / 255.0;
  994.     }
  995.  
  996.     *index = -1;
  997.   }
  998.   else
  999.   {
  1000.     *index = Image->data.map_lines[iycoor][ixcoor];
  1001.  
  1002.     map_colour = &Image->Colour_Map[*index];
  1003.  
  1004.     colour[RED] += (DBL)map_colour->Red / 255.0;
  1005.     colour[GREEN] += (DBL)map_colour->Green / 255.0;
  1006.     colour[BLUE] += (DBL)map_colour->Blue / 255.0;
  1007.     colour[FILTER] += (DBL)map_colour->Filter / 255.0;
  1008.     colour[TRANSM] += (DBL)map_colour->Transmit / 255.0;
  1009.   }
  1010. }
  1011.  
  1012.  
  1013.  
  1014. /*****************************************************************************
  1015. *
  1016. * FUNCTION
  1017. *
  1018. * INPUT
  1019. *
  1020. * OUTPUT
  1021. *
  1022. * RETURNS
  1023. *
  1024. * AUTHOR
  1025. *
  1026. * DESCRIPTION
  1027. *
  1028. * CHANGES
  1029. *
  1030. ******************************************************************************/
  1031.  
  1032. /* Interpolate color and filter values when mapping */
  1033.  
  1034. static void Interp(Image, xcoor, ycoor, colour, index)
  1035. IMAGE *Image;
  1036. DBL xcoor, ycoor;
  1037. COLOUR colour;
  1038. int *index;
  1039. {
  1040.   int iycoor, ixcoor, i;
  1041.   int Corners_Index[4];
  1042.   DBL Index_Crn[4];
  1043.   COLOUR Corner_Colour[4];
  1044.   DBL Red_Crn[4];
  1045.   DBL Green_Crn[4];
  1046.   DBL Blue_Crn[4];
  1047.   DBL Filter_Crn[4];
  1048.   DBL Transm_Crn[4];
  1049.   DBL val1, val2, val3, val4, val5;
  1050.  
  1051.   val1 = val2 = val3 = val4 = val5 = 0.0;
  1052.  
  1053.   iycoor = (int)ycoor;
  1054.   ixcoor = (int)xcoor;
  1055.  
  1056.   for (i = 0; i < 4; i++)
  1057.   {
  1058.     Make_ColourA(Corner_Colour[i], 0.0, 0.0, 0.0, 0.0, 0.0);
  1059.   }
  1060.  
  1061.   /* OK, now that you have the corners, what are you going to do with them? */
  1062.  
  1063.   if (Image->Interpolation_Type == BILINEAR)
  1064.   {
  1065.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[0], &Corners_Index[0]);
  1066.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[1], &Corners_Index[1]);
  1067.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2]);
  1068.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3]);
  1069.  
  1070.     for (i = 0; i < 4; i++)
  1071.     {
  1072.       Red_Crn[i] = Corner_Colour[i][RED];
  1073.       Green_Crn[i] = Corner_Colour[i][GREEN];
  1074.       Blue_Crn[i] = Corner_Colour[i][BLUE];
  1075.       Filter_Crn[i] = Corner_Colour[i][FILTER];
  1076.       Transm_Crn[i] = Corner_Colour[i][TRANSM];
  1077.  
  1078.       /*
  1079.        * Debug_Info("Crn %d = %lf %lf
  1080.        * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  1081.        */
  1082.     }
  1083.  
  1084.     val1 = bilinear(Red_Crn, xcoor, ycoor);
  1085.     val2 = bilinear(Green_Crn, xcoor, ycoor);
  1086.     val3 = bilinear(Blue_Crn, xcoor, ycoor);
  1087.     val4 = bilinear(Filter_Crn, xcoor, ycoor);
  1088.     val5 = bilinear(Transm_Crn, xcoor, ycoor);
  1089.   }
  1090.  
  1091.   if (Image->Interpolation_Type == NORMALIZED_DIST)
  1092.   {
  1093.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[0], &Corners_Index[0]);
  1094.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[1], &Corners_Index[1]);
  1095.     no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[2], &Corners_Index[2]);
  1096.     no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[3], &Corners_Index[3]);
  1097.  
  1098.     for (i = 0; i < 4; i++)
  1099.     {
  1100.       Red_Crn[i] = Corner_Colour[i][RED];
  1101.       Green_Crn[i] = Corner_Colour[i][GREEN];
  1102.       Blue_Crn[i] = Corner_Colour[i][BLUE];
  1103.       Filter_Crn[i] = Corner_Colour[i][FILTER];
  1104.       Transm_Crn[i] = Corner_Colour[i][TRANSM];
  1105.  
  1106.       /*
  1107.        * Debug_Info("Crn %d = %lf %lf
  1108.        * %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]);
  1109.        */
  1110.     }
  1111.  
  1112.     val1 = norm_dist(Red_Crn, xcoor, ycoor);
  1113.     val2 = norm_dist(Green_Crn, xcoor, ycoor);
  1114.     val3 = norm_dist(Blue_Crn, xcoor, ycoor);
  1115.     val4 = norm_dist(Filter_Crn, xcoor, ycoor);
  1116.     val5 = norm_dist(Transm_Crn, xcoor, ycoor);
  1117.   }
  1118.  
  1119.   colour[RED] += val1;
  1120.   colour[GREEN] += val2;
  1121.   colour[BLUE] += val3;
  1122.   colour[FILTER] += val4;
  1123.   colour[TRANSM] += val5;
  1124.  
  1125.   /* Debug_Info("Final = %lf %lf %lf\n",val1,val2,val3);  */
  1126.   /* use bilinear for index try average later */
  1127.  
  1128.   for (i = 0; i < 4; i++)
  1129.   {
  1130.     Index_Crn[i] = (DBL)Corners_Index[i];
  1131.   }
  1132.  
  1133.   if (Image->Interpolation_Type == BILINEAR)
  1134.   {
  1135.     *index = (int)(bilinear(Index_Crn, xcoor, ycoor) + 0.5);
  1136.   }
  1137.  
  1138.   if (Image->Interpolation_Type == NORMALIZED_DIST)
  1139.   {
  1140.     *index = (int)(norm_dist(Index_Crn, xcoor, ycoor) + 0.5);
  1141.   }
  1142. }
  1143.  
  1144.  
  1145.  
  1146. /*****************************************************************************
  1147. *
  1148. * FUNCTION
  1149. *
  1150. * INPUT
  1151. *
  1152. * OUTPUT
  1153. *
  1154. * RETURNS
  1155. *
  1156. * AUTHOR
  1157. *
  1158. * DESCRIPTION
  1159. *
  1160. * CHANGES
  1161. *
  1162. ******************************************************************************/
  1163.  
  1164. /* These interpolation techniques are taken from an article by */
  1165. /* Girish T. Hagan in the C Programmer's Journal V 9 No. 8 */
  1166. /* They were adapted for POV-Ray by CdW */
  1167.  
  1168. static DBL bilinear(corners, x, y)
  1169. DBL *corners, x, y;
  1170. {
  1171.   DBL p, q;
  1172.   DBL val;
  1173.  
  1174.   p = x - (int)x;
  1175.   q = y - (int)y;
  1176.  
  1177.   if ((p == 0.0) && (q == 0.0))
  1178.   {
  1179.     return (*corners);  /* upper left */
  1180.   }
  1181.  
  1182.   val = (p * q * *corners) + (q * (1 - p) * *(corners + 1)) +
  1183.     (p * (1 - q) * *(corners + 2)) + ((1 - p) * (1 - q) * *(corners + 3));
  1184.  
  1185.   return (val);
  1186. }
  1187.  
  1188.  
  1189.  
  1190.  
  1191. /*****************************************************************************
  1192. *
  1193. * FUNCTION
  1194. *
  1195. * INPUT
  1196. *
  1197. * OUTPUT
  1198. *
  1199. * RETURNS
  1200. *
  1201. * AUTHOR
  1202. *
  1203. * DESCRIPTION
  1204. *
  1205. * CHANGES
  1206. *
  1207. ******************************************************************************/
  1208.  
  1209. #define MAX_PTS 4
  1210. #define PYTHAGOREAN_SQ(a,b)  ( (a)*(a) + (b)*(b) )
  1211.  
  1212. static DBL norm_dist(corners, x, y)
  1213. DBL *corners, x, y;
  1214. {
  1215.   register int i;
  1216.  
  1217.   DBL p, q;
  1218.   DBL wts[MAX_PTS];
  1219.   DBL sum_inv_wts = 0.0;
  1220.   DBL sum_I = 0.0;
  1221.  
  1222.   p = x - (int)x;
  1223.   q = y - (int)y;
  1224.  
  1225.   if ((p == 0.0) && (q == 0.0))
  1226.   {
  1227.     return (*corners);  /* upper left */
  1228.   }
  1229.  
  1230.   wts[0] = PYTHAGOREAN_SQ(p, q);
  1231.   wts[1] = PYTHAGOREAN_SQ(1 - p, q);
  1232.   wts[2] = PYTHAGOREAN_SQ(p, 1 - q);
  1233.   wts[3] = PYTHAGOREAN_SQ(1 - p, 1 - q);
  1234.  
  1235.   for (i = 0; i < MAX_PTS; i++)
  1236.   {
  1237.     sum_inv_wts += 1 / wts[i];
  1238.  
  1239.     sum_I += *(corners + i) / wts[i];
  1240.   }
  1241.  
  1242.   return (sum_I / sum_inv_wts);
  1243. }
  1244.  
  1245.  
  1246.  
  1247. /*****************************************************************************
  1248. *
  1249. * FUNCTION
  1250. *
  1251. *   Create_Image
  1252. *
  1253. * INPUT
  1254. *
  1255. * OUTPUT
  1256. *
  1257. * RETURNS
  1258. *
  1259. * AUTHOR
  1260. *
  1261. *   POV-Ray Team
  1262. *
  1263. * DESCRIPTION
  1264. *
  1265. *   -
  1266. *
  1267. * CHANGES
  1268. *
  1269. *   -
  1270. *
  1271. ******************************************************************************/
  1272.  
  1273. IMAGE *Create_Image()
  1274. {
  1275.   IMAGE *Image;
  1276.  
  1277.   Image = (IMAGE *) POV_MALLOC(sizeof(IMAGE), "image file");
  1278.  
  1279.   Image->References = 1;
  1280.  
  1281.   Image->File_Type = NO_FILE;
  1282.  
  1283.   Image->Map_Type = PLANAR_MAP;
  1284.  
  1285.   Image->Interpolation_Type = NO_INTERPOLATION;
  1286.  
  1287.   Image->Once_Flag = FALSE;
  1288.  
  1289.   Image->Use_Colour_Flag = FALSE;
  1290.  
  1291.   Make_Vector(Image->Gradient, 1.0, -1.0, 0.0);
  1292.  
  1293.   return (Image);
  1294. }
  1295.  
  1296.  
  1297.  
  1298. /*****************************************************************************
  1299. *
  1300. * FUNCTION
  1301. *
  1302. *   Copy_Image
  1303. *
  1304. * INPUT
  1305. *
  1306. * OUTPUT
  1307. *
  1308. * RETURNS
  1309. *
  1310. * AUTHOR
  1311. *
  1312. *   POV-Ray Team
  1313. *
  1314. * DESCRIPTION
  1315. *
  1316. *   -
  1317. *
  1318. * CHANGES
  1319. *
  1320. *   -
  1321. *
  1322. ******************************************************************************/
  1323.  
  1324. IMAGE *Copy_Image(Old)
  1325. IMAGE *Old;
  1326. {
  1327.   if (Old != NULL)
  1328.   {
  1329.     Old->References++;
  1330.   }
  1331.  
  1332.   return (Old);
  1333. }
  1334.  
  1335.  
  1336.  
  1337. /*****************************************************************************
  1338. *
  1339. * FUNCTION
  1340. *
  1341. *   Destroy_Image
  1342. *
  1343. * INPUT
  1344. *
  1345. * OUTPUT
  1346. *
  1347. * RETURNS
  1348. *
  1349. * AUTHOR
  1350. *
  1351. *   POV-Ray Team
  1352. *
  1353. * DESCRIPTION
  1354. *
  1355. *   -
  1356. *
  1357. * CHANGES
  1358. *
  1359. *   -
  1360. *
  1361. ******************************************************************************/
  1362.  
  1363. void Destroy_Image(Image)
  1364. IMAGE *Image;
  1365. {
  1366.   int i;
  1367.  
  1368.   if ((Image == NULL) || (--(Image->References) > 0))
  1369.   {
  1370.     return;
  1371.   }
  1372.  
  1373.   if (Image->Colour_Map != NULL)
  1374.   {
  1375.     POV_FREE(Image->Colour_Map);
  1376.  
  1377.     Image->Colour_Map = NULL;
  1378.  
  1379.     if (Image->data.map_lines != NULL)
  1380.     {
  1381.       for (i = 0; i < Image->iheight; i++)
  1382.       {
  1383.         POV_FREE(Image->data.map_lines[i]);
  1384.       }
  1385.  
  1386.       POV_FREE(Image->data.map_lines);
  1387.  
  1388.       Image->data.map_lines = NULL;
  1389.     }
  1390.   }
  1391.   else
  1392.   {
  1393.     if (Image->data.rgb_lines != NULL)
  1394.     {
  1395.       for (i = 0; i < Image->iheight; i++)
  1396.       {
  1397.         POV_FREE(Image->data.rgb_lines[i].red);
  1398.         POV_FREE(Image->data.rgb_lines[i].green);
  1399.         POV_FREE(Image->data.rgb_lines[i].blue);
  1400.  
  1401.         if (Image->data.rgb_lines[i].transm != NULL)
  1402.         {
  1403.           POV_FREE(Image->data.rgb_lines[i].transm);
  1404.         }
  1405.       }
  1406.  
  1407.       POV_FREE(Image->data.rgb_lines);
  1408.  
  1409.       Image->data.rgb_lines = NULL;
  1410.     }
  1411.   }
  1412.  
  1413.   POV_FREE(Image);
  1414. }
  1415.